package factory;

import gameobject.Sprite;
import java.awt.Point;
import java.util.ArrayList;
import java.util.List;
import simulation.Game;

public class ShootingAliensFactory extends Factory implements Runnable{
    private String[] parameters;
    private String className;
    private String myLine;

    private List<Sprite> myProducts;
    private List<Point> myPositions;
    private List<Double> myProbabilities;

    private int myTotalNumber;
    //number of enemies that has been generated so far
    private int myNumberGenerated = 0;
    private int myNumberOfType;

    /** 
     * Constructor of this factory 
     * 
     * @param address path name of the file for factory to read in information needed for construction
     * @param game the GameSimulation objects for factory to access the list of sprites 
     */
    public ShootingAliensFactory(String address, int delayTime, Game game) {
        super(address, delayTime, game);
    }

    /** 
     * This class can be overriden to apply different ways of generating sprites
     */
    @Override
    public void startGeneration() {
        myProducts = new ArrayList<Sprite>();
        myPositions = new ArrayList<Point>();

        myLine = readNextLine();
        myTotalNumber = Integer.parseInt(myLine);
        myLine = readNextLine();
        myNumberOfType = Integer.parseInt(myLine);
        readProbabilities();

        for (int i = 0; i < myNumberOfType; i++) {
            myLine = readNextLine();
            boolean isPrototype = checkIsPrototype(myLine);
            if (!isPrototype) {
                myLine = myLine.substring(myLine.indexOf("!") + 1);
            }
            processLine(isPrototype);
        }
    }

    protected void readProbabilities() {
        myProbabilities = new ArrayList<Double>();
        myLine = readNextLine();
        String[] probabilities = myLine.split(" ");
        double accumulativeProbability = 0;
        for (String s: probabilities) {
            accumulativeProbability += Double.parseDouble(s);
            myProbabilities.add(accumulativeProbability);
        }
    }

    /** 
     * process the file of this specific syntax 
     * override if the syntax is different 
     *
     **/
    protected void processLine(boolean isPrototype) {
        className = "gameobject." + extractNextWord(myLine);
        myLine = deleteNextWord(myLine);
        Point myPosition = readPosition();
        parameters = myLine.split(" ");
        
        Sprite mySprite = null;
        try {
            mySprite = (Sprite)(Class.forName(className).newInstance());
        }
        catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        catch (InstantiationException e) {
            e.printStackTrace();
        }
        catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        Sprite myProduct = mySprite.createProduct(getGame(), parameters);
        if (isPrototype) {
            myPositions.add(myPosition);
            myProducts.add(myProduct);
        }
        else {
            finalizeProduct(myProduct, myPosition);
        }
    }

    /** 
     * set necessary variables and put it into the list for use 
     * 
     * @param product Sprite product
     * @param position position to be put on the Canvas
     * @return 
     */
    protected void finalizeProduct(Sprite product, Point position) {
        product.setPosition(position);
        product.setDimension(getCanvasDimension());
        getGame().addSprite(product);
        product.activate();
    }

    protected boolean checkIsPrototype(String line) {
        return line.indexOf("!") < 0;
    }

    protected void instantiateByClassName(String info) {
        processLine(false);
    }

    protected Point readPosition() {
        Point myPosition = new Point();
        myPosition.x = Integer.parseInt(extractNextWord(myLine));
        myLine = deleteNextWord(myLine);
        myPosition.y = Integer.parseInt(extractNextWord(myLine));
        myLine = deleteNextWord(myLine);
        return myPosition;
    } 

    protected String extractNextWord(String line) {
        int firstSpace = line.indexOf(" ");
        String word = line.substring(0, firstSpace).trim();
        return word; }

    protected String deleteNextWord(String line) {
        int firstSpace = line.indexOf(" ");
        line = line.substring(firstSpace).trim();
        return line;
    }

    @Override
    public void generateSprites() {
        double myRandomNumber = Math.random();
        int i;
        for (i = 0; i < myProbabilities.size(); i++) {
            if (myRandomNumber < myProbabilities.get(i)) {
                break;
            }
        }
        Sprite myChosenProduct = null;
        try {
            myChosenProduct = (Sprite)(myProducts.get(i).clone());
        }
        catch(CloneNotSupportedException e) {
            System.err.println(myChosenProduct.getClass()); e.printStackTrace();
        }
        Point myChosenPosition = new Point(myPositions.get(i));
        if (myChosenPosition.x == -1) {
            myChosenPosition.x = (int)(Math.random() * getCanvasDimension().width); 
        }
        if (myChosenPosition.y == -1) {
            myChosenPosition.y = (int)(Math.random() * getCanvasDimension().height/3); 
        }
        finalizeProduct(myChosenProduct, myChosenPosition);

        myNumberGenerated ++;
        if (myNumberGenerated == myTotalNumber) {
            stop();
        }
    }
}
